#ifndef Data_First
#define Data_First
#ifdef __GNUG__
#pragma interface
#endif

#include "RefCounted.h"
#include "Symbol.h"

class StreamBuf;
class MemBuf;
class Bitmap;
class SeqCollection;
class Converter;
class TypeMatcher;

extern const Symbol
	cDocTypeUndef,      // "UNDEF" document type
	cDocTypeAscii,      // document type for ordinary ascii-files
	cDocTypeET,         // ET++ file format
	cDocTypeCPlusPlus,
	cDocTypeCHeader,
	cDocTypeDirectory,  // System directory
	cDocTypeExec,
	cDocTypeOFile;      // .o file

extern const Symbol
	cDocCreatorUndef;   // Creator of document unknown

enum {
	eDataType,
	eDataCreator,
	eDataSize,
	eDataTime,
	eDataId,
	eDataExec,
	eDataValid,
	eDataWrite,
	eDataRead,
	eDataDeepType,
	eDataNew
};

//---- Data --------------------------------------------------------------------

class Data : public RefCounted {
public:
	MetaDef(Data);
	Data(const char *name= 0);
	~Data();

	void UpdateBit(u_long b, bool val);

	virtual const char *FullName();
	virtual const char *ShortName();
	const char *Name();

	Class *GetClassType();
	void SetClassType(Class *cl);

	bool IsUntitled();
	const Symbol &Type();
	void SetType(const Symbol &t);
	const Symbol &Creator();
	void SetCreator(const Symbol &crea);

	virtual StreamBuf *GetStreamBuf(bool forwriting);
	StreamBuf *GetStreamBufForReading();
	StreamBuf *GetStreamBufForWriting();
	virtual void StartUpdate();
	virtual void EndUpdate(bool isok, bool removebackup);

	virtual Bitmap *GetBitmap();

	virtual SeqCollection *GetContents();
	virtual bool HasContents();

	virtual Data *GetParent();
	bool HasParent();

	bool IsWritable();
	bool IsReadable();
	bool IsExecutable();
	bool IsValid();

	bool IsDirectory();
	bool IsETFormat();
	bool IsAscii();

	u_long UniqueId();
	long SizeHint();

	u_long ModifiedAt();

	virtual Object *AsObject(Class *want);
	virtual bool CanConvert(Class *want);
	virtual bool CheckTypes(OrdCollection *typelist);

	int Compare(Object *op);
	u_long Hash();
	bool IsEqual(Object *op);
	const char *AsString();

	OStream& PrintOn(OStream&);
	IStream& ReadFrom(IStream&);

protected:
	virtual u_long UpdateFields(u_long flags);
	virtual Object *MakeObject(Class *want);

protected:
	u_long flags, bits, modtime, uniqueid;
	long sizehint;
	char *name;
	Symbol creator, type;
	Class *classtype;
	TypeMatcher *typematcher;
};

inline const char *Data::Name()
	{ return FullName(); }
inline void Data::SetClassType(Class *cl)
	{ classtype= cl; }
inline bool Data::IsDirectory()
	{ return HasContents(); }

//---- StreamBufData -----------------------------------------------------------

class StreamBufData : public Data {
public:
	MetaDef(StreamBufData);
	StreamBufData(StreamBuf *sb= 0, const Symbol &type= cDocTypeUndef);
	StreamBuf *GetStreamBuf(bool forwriting);
protected:
	StreamBuf *sb;
};

//---- MemoryData --------------------------------------------------------------

class MemoryData : public Data {
public:
	MetaDef(MemoryData);
	MemoryData(byte *data, int len, const Symbol &type= cDocTypeUndef,
				bool copy= TRUE, bool dodelete= TRUE);
	~MemoryData();
	StreamBuf *GetStreamBuf(bool forwriting);
	OStream& PrintOn(OStream &s);
	IStream& ReadFrom(IStream &s);
protected:
	byte *data;
	bool dodelete;
};

//---- ObjectData --------------------------------------------------------------

class ObjectData : public Data {
public:
	MetaDef(ObjectData);
	ObjectData(Object *op);
	~ObjectData();
	bool CanConvert(Class *want);
	Object *MakeObject(Class *want);
	OStream& PrintOn(OStream&);
	IStream& ReadFrom(IStream&);
protected:
	Object *object;
};

#endif
